{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "90dc5b57-2ec5-4c53-8276-b38d4aa23af3",
   "metadata": {},
   "source": [
    "## About\n",
    "It is anticipated that the `developer` exploring this blueprint will likely follow one of the two paths i.e.\n",
    "* Build your own conversational agent from the grounds up\n",
    "* Extend an existing agent\n",
    "\n",
    "The blueprint has two sets of APIs the application builder is expected to interact with. The blueprint is expected to be deployed using docker compose for this APIs to be accesible.\n",
    "\n",
    "* Agent apis\n",
    "This is exposed on port 8081 and accessible on \"http://IPADDR:8081\".\n",
    "Api documentation is available at  \"http://IPADDR:8081/docs#\"\n",
    "\n",
    "* Analytics server apis\n",
    "This is exposed on port 8082 and accessible on \"http://IPADDR:8082\".\n",
    "Api documentation is available at  \"http://IPADDR:8082/docs#\" \n",
    "\n",
    "This notebook further illustrates one more aspect which becomes important when the `customer service operations` team wants to leverage the user feedback to power the data flywheel. Examples are included on how to glean the feedback data from the blueprint."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5d2c5e5a-5f73-4794-9065-d2d1554af40f",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install requests"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9f41d0f-0eea-47e2-a715-ecf716f16181",
   "metadata": {},
   "source": [
    "### Notebook variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8bbae037-6a63-40ef-8d46-18f706855f63",
   "metadata": {},
   "outputs": [],
   "source": [
    "IPADDRESS = \"localhost\" #Replace this with the correct IP address\n",
    "AGENT_PORT = \"8081\"\n",
    "ANALYTICS_PORT = \"8082\"\n",
    "AGENT_BASE_URL = f'http://{IPADDRESS}:{AGENT_PORT}'\n",
    "ANALYTICS_BASE_URL = f'http://{IPADDRESS}:{ANALYTICS_PORT}'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b45d8a18-9c1f-4705-a9cf-99ac4324b43a",
   "metadata": {},
   "source": [
    "### Agent API usage\n",
    "The next few set of cells illustrate examples of the APIs as documented at \n",
    "http://localhost:8081/docs#"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c6d18c97-ec01-411c-8c08-9e7aaeb6bde2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Health\n",
    "# Perform a Health Check\n",
    "import requests\n",
    "url = AGENT_BASE_URL + \"/health\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\"\n",
    "}\n",
    "response = requests.get(url, headers=headers)\n",
    "\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "print(\"Response Body:\", response.json())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1fa1ef6e-df8b-4c46-8bf9-93956064b6c4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Metrics\n",
    "\n",
    "import requests\n",
    "url = AGENT_BASE_URL + \"/metrics\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\"\n",
    "}\n",
    "response = requests.get(url, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "try:\n",
    "    print(\"Response Body:\", response.json())\n",
    "except ValueError:\n",
    "    print(\"Response is not in JSON format:\", response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fd68e2a7-abf3-493a-85fd-3d894f9edb5d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# create_session\n",
    "# This needs to be done at the commencement of a conversation.\n",
    "# The returned the session_id needs to be used in the conversation that ensues\n",
    "import requests\n",
    "url = AGENT_BASE_URL + \"/create_session\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\"\n",
    "}\n",
    "response = requests.get(url, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "if response.status_code == 200:\n",
    "    try:\n",
    "        data = response.json()\n",
    "        session_id = data.get(\"session_id\")\n",
    "        print(\"Session ID:\", session_id)\n",
    "    except ValueError:\n",
    "        print(\"Response is not in JSON format:\", response.text)\n",
    "else:\n",
    "    print(\"Failed to create session. Status Code:\", response.status_code)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9fa7b321-b34b-4532-ab71-d9af75f6120d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# generate\n",
    "# user_id is set to John Doe (refer the customer data csv)\n",
    "# session_id from the \"create_session\" is used in the post request\n",
    "\n",
    "import requests\n",
    "url = AGENT_BASE_URL + \"/generate\"  # Replace with the appropriate endpoint\n",
    "headers = {\n",
    "    \"Content-Type\": \"application/json\",\n",
    "    \"accept\": \"application/json\"\n",
    "}\n",
    "payload = {\n",
    "    \"messages\": [\n",
    "        {\n",
    "            \"role\": \"user\",\n",
    "            \"content\": \"What is the return status for my GeForce RTX 4070 SUPER??\"\n",
    "        }\n",
    "    ],\n",
    "    \"user_id\": \"4165\",  # Replace with the actual user ID\n",
    "    \"session_id\": f\"{session_id}\"  # Replace with the actual session ID\n",
    "}\n",
    "\n",
    "response = requests.post(url, json=payload, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "try:\n",
    "    print(\"Response Body:\", response.json())\n",
    "except ValueError:\n",
    "    print(\"Response is not in JSON format:\", response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "db76214f-f520-4f09-9d29-c52378f2b9ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "# feedback/response\n",
    "# The feedback pertains to the most recent response as per \"generate\" api\n",
    "# feedback convention: -1:Negative, 0:Neutral, 1=Positive\n",
    "import requests\n",
    "\n",
    "url = AGENT_BASE_URL + \"/feedback/response\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\",\n",
    "    \"Content-Type\": \"application/json\"\n",
    "}\n",
    "payload = {\n",
    "    \"feedback\": -1,\n",
    "    \"session_id\": f\"{session_id}\"  # Replace with the actual session ID\n",
    "}\n",
    "response = requests.post(url, json=payload, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "try:\n",
    "    print(\"Response Body:\", response.json())\n",
    "except ValueError:\n",
    "    print(\"Response is not in JSON format:\", response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cf7be7cc-3620-4e33-9750-833a5c98e4ac",
   "metadata": {},
   "outputs": [],
   "source": [
    "# end_session\n",
    "\n",
    "import requests\n",
    "url = f\"{AGENT_BASE_URL}/end_session?session_id={session_id}\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\"\n",
    "}\n",
    "response = requests.get(url, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "try:\n",
    "    print(\"Response Body:\", response.json())\n",
    "except ValueError:\n",
    "    print(\"Response is not in JSON format:\", response.text)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "120999a0-c48e-404f-a1c5-82716c00c466",
   "metadata": {
    "id": "79acf105-e367-4d2b-b8d9-c272eca23064"
   },
   "source": [
    "### Analytics API usage\n",
    "The next few set of cells illustrate examples of the APIs as documented at \n",
    "http://localhost:8082/docs#"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "65db2af4-4f5f-41ac-a2fb-74eb7450613d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Health\n",
    "# performs a health check\n",
    "import requests\n",
    "url = ANALYTICS_BASE_URL + \"/health\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\"\n",
    "}\n",
    "response = requests.get(url, headers=headers)\n",
    "\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "print(\"Response Body:\", response.json())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81b3e019-fefb-4ee3-89a1-f95e2c778a02",
   "metadata": {},
   "outputs": [],
   "source": [
    "# sessions\n",
    "# Retrieve session information in last 2 hours\n",
    "\n",
    "import requests\n",
    "\n",
    "url = f\"{ANALYTICS_BASE_URL}/sessions?hours=2\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\"\n",
    "}\n",
    "response = requests.get(url, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "try:\n",
    "    print(\"Response Body:\", response.json())\n",
    "except ValueError:\n",
    "    print(\"Response is not in JSON format:\", response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2730fd29-41fc-417c-8899-fdbc5015c53c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# conversation?session_id=xyz\n",
    "# fetch the conversation history given a session id\n",
    "\n",
    "import requests\n",
    "print(\"session_id :{}\".format(session_id))\n",
    "url = f\"{ANALYTICS_BASE_URL}/session/conversation?session_id={session_id}\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\"\n",
    "}\n",
    "response = requests.get(url, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "try:\n",
    "    print(\"Response Body:\", response.json())\n",
    "except ValueError:\n",
    "    print(\"Response is not in JSON format:\", response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "10ae404d-379e-4d0e-b33f-99850bd279d5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# session/summary\n",
    "# generate the conversation summary given a session_id\n",
    "\n",
    "import requests\n",
    "print(\"session_id :{}\".format(session_id))\n",
    "url = f\"{ANALYTICS_BASE_URL}/session/summary?session_id={session_id}\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\"\n",
    "}\n",
    "response = requests.get(url, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "try:\n",
    "    print(\"Response Body:\", response.json())\n",
    "except ValueError:\n",
    "    print(\"Response is not in JSON format:\", response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb9a3e21-bdef-4923-966e-e52454c138d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "## feedback/summary\n",
    "## store the feedback for the summary generated by the solution\n",
    "# feedback convention: -1:Negative, 0:Neutral, 1=Positive\n",
    "\n",
    "url = ANALYTICS_BASE_URL + \"/feedback/summary\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\",\n",
    "    \"Content-Type\": \"application/json\"\n",
    "}\n",
    "payload = {\n",
    "    \"feedback\": +1, # positive\n",
    "    \"session_id\": f\"{session_id}\"  # Replace with the actual session ID\n",
    "}\n",
    "response = requests.post(url, json=payload, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "try:\n",
    "    print(\"Response Body:\", response.json())\n",
    "except ValueError:\n",
    "    print(\"Response is not in JSON format:\", response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6d14677a-c269-4943-a755-5f57388ea7c7",
   "metadata": {},
   "outputs": [],
   "source": [
    "## feedback/session\n",
    "## store user feedback for the overall conversation session.\n",
    "# feedback convention: -1:Negative, 0:Neutral, 1=Positive\n",
    "\n",
    "url = ANALYTICS_BASE_URL + \"/feedback/session\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\",\n",
    "    \"Content-Type\": \"application/json\"\n",
    "}\n",
    "payload = {\n",
    "    \"feedback\": -1, # negative\n",
    "    \"session_id\": f\"{session_id}\"  # Replace with the actual session ID\n",
    "}\n",
    "response = requests.post(url, json=payload, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "try:\n",
    "    print(\"Response Body:\", response.json())\n",
    "except ValueError:\n",
    "    print(\"Response is not in JSON format:\", response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "845f728a-dde4-43e3-9a4f-3997026df898",
   "metadata": {},
   "outputs": [],
   "source": [
    "## feedback/sentiment\n",
    "## store rating for the sentiment generated by the solution\n",
    "# feedback convention: -1:Negative, 0:Neutral, 1=Positive\n",
    "\n",
    "url = ANALYTICS_BASE_URL + \"/feedback/sentiment\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\",\n",
    "    \"Content-Type\": \"application/json\"\n",
    "}\n",
    "payload = {\n",
    "    \"feedback\": 0, # neutral\n",
    "    \"session_id\": f\"{session_id}\"  # Replace with the actual session ID\n",
    "}\n",
    "response = requests.post(url, json=payload, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "try:\n",
    "    print(\"Response Body:\", response.json())\n",
    "except ValueError:\n",
    "    print(\"Response is not in JSON format:\", response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28686a35-8398-471f-b0f5-72a4b464ec83",
   "metadata": {},
   "outputs": [],
   "source": [
    "# delete_session\n",
    "\n",
    "import requests\n",
    "url = f\"{AGENT_BASE_URL}/delete_session?session_id={session_id}\"\n",
    "headers = {\n",
    "    \"accept\": \"application/json\"\n",
    "}\n",
    "response = requests.delete(url, headers=headers)\n",
    "# Print the response\n",
    "print(\"Status Code:\", response.status_code)\n",
    "try:\n",
    "    print(\"Response Body:\", response.json())\n",
    "except ValueError:\n",
    "    print(\"Response is not in JSON format:\", response.text)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69bf3f93-c16f-456b-bcbb-77690b9d6fdf",
   "metadata": {},
   "source": [
    "### Accessing User Feedback data\n",
    "The next few set of cells illustrate how the various types of feedback data can be collected to power the data flywheel.\n",
    "Refer to the docker-compose.yaml or helm chart for the credentials of the postgres db"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "b8499446-b0e5-4979-9b10-f4f104d3b7d5",
   "metadata": {},
   "outputs": [],
   "source": [
    "POSTGRES_HOST = \"localhost\"\n",
    "POSTGRESDB_PORT = \"5432\"\n",
    "POSTGRES_USER = \"postgres\"\n",
    "POSTGRES_PASSWD = \"password\"\n",
    "POSTGRES_DBNAME = \"postgres\"\n",
    "FEEDBACK_TBLNAME = \"feedback\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60d76713-21fc-46ce-89d5-7331bb738aae",
   "metadata": {},
   "source": [
    "#### Schema information of the `feedback` table"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "6d193e1e-63f8-48b6-b7da-4593e8af98ff",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Schema for public.feedback:\n",
      " - session_id: character varying\n",
      " - sentiment: double precision\n",
      " - summary: double precision\n",
      " - session: double precision\n"
     ]
    }
   ],
   "source": [
    "import psycopg2\n",
    "\n",
    "# Connection details\n",
    "host = POSTGRES_HOST\n",
    "port = POSTGRESDB_PORT\n",
    "database = POSTGRES_DBNAME\n",
    "user = POSTGRES_USER\n",
    "password = POSTGRES_PASSWD\n",
    "\n",
    "# The schema and table you're interested in\n",
    "schema_name = \"public\"      # replace if needed\n",
    "table_name = FEEDBACK_TBLNAME   # replace with the actual table name\n",
    "\n",
    "try:\n",
    "    # Connect to the PostgreSQL database\n",
    "    conn = psycopg2.connect(\n",
    "        host=host,\n",
    "        port=port,\n",
    "        database=database,\n",
    "        user=user,\n",
    "        password=password\n",
    "    )\n",
    "    cursor = conn.cursor()\n",
    "\n",
    "    # Query to get column details of a specific table\n",
    "    # information_schema.columns provides column_name and data_type\n",
    "    query = \"\"\"\n",
    "        SELECT column_name, data_type\n",
    "        FROM information_schema.columns\n",
    "        WHERE table_name = %s AND table_schema = %s\n",
    "        ORDER BY ordinal_position;\n",
    "    \"\"\"\n",
    "    cursor.execute(query, (table_name, schema_name))\n",
    "\n",
    "    columns = cursor.fetchall()\n",
    "\n",
    "    # Print the schema details\n",
    "    print(f\"Schema for {schema_name}.{table_name}:\")\n",
    "    for col in columns:\n",
    "        col_name, data_type = col\n",
    "        print(f\" - {col_name}: {data_type}\")\n",
    "\n",
    "except Exception as e:\n",
    "    print(\"Error:\", e)\n",
    "finally:\n",
    "    if 'cursor' in locals():\n",
    "        cursor.close()\n",
    "    if 'conn' in locals():\n",
    "        conn.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b53c551b-402f-4e6c-98f1-eaa75d19a941",
   "metadata": {},
   "source": [
    "#### Retrieve the feedback information for each session(session_id)\n",
    "* sentiment\n",
    "* summary\n",
    "* session\n",
    "\n",
    "These fields can take on a value such as\n",
    "\n",
    "1:Positive,\n",
    "0:Neutral,\n",
    "-1:Negative"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b5dd00fd-68b4-4932-95a4-b4f50c45cf06",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1:('string', -1.0, None, None)\n",
      "2:('188b3c82-3384-4c6b-94cb-024d24b312d2', -1.0, 1.0, None)\n"
     ]
    }
   ],
   "source": [
    "import psycopg2\n",
    "\n",
    "# Database connection parameters\n",
    "db_params = {\n",
    "    'dbname': POSTGRES_DBNAME,\n",
    "    'user': POSTGRES_USER,\n",
    "    'password': POSTGRES_PASSWD,\n",
    "    'host': POSTGRES_HOST,      # e.g., 'localhost' or the IP address\n",
    "    'port': POSTGRESDB_PORT   # e.g., '5432'\n",
    "}\n",
    "\n",
    "# Connect to the database\n",
    "conn = psycopg2.connect(**db_params)\n",
    "cur = conn.cursor()\n",
    "\n",
    "# Query to select the first 5 rows from the customer_data table\n",
    "query = f'SELECT session_id, sentiment, summary, session FROM feedback;'\n",
    "# Execute the query\n",
    "cur.execute(query)\n",
    "rows = cur.fetchall()\n",
    "\n",
    "# Print the headers and the corresponding rows\n",
    "for i, row in enumerate(rows, start=1):\n",
    "    print(f\"{i}:{row}\")\n",
    "\n",
    "    # Close the connection\n",
    "cur.close()\n",
    "conn.close()"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
